/*
 * ParserTrainer.cpp
 *
 *  Created on: Mar 20, 2013
 *      Author: ayran
 */

#include <cctype>
#include <iostream>
#include "../include/ParserTrainer.h"

ParserTrainer::ParserTrainer() {
}

ParserTrainer::ParserTrainer(std::string msg):expression(msg),index(0) {
}

ParserTrainer::~ParserTrainer() {
}

char
ParserTrainer::getChar()/*Avancar uma posição na string[]*/
{
	if (index == expression.length())
		return '\0';

	return expression[index++];
}

void
ParserTrainer::pushChar() { /*Retorna uma posicao na string[]*/
		--index;
}

void
ParserTrainer::skipWhiteSpaces() {/*Inginora espacos em brancos ate achar o fim da string[]*/
	while (true) {
		char c = getChar();

		if (c == '\0')
			break;

		if (!isblank(c)) {
			pushChar();
			break;
		}
	}

}




bool
ParserTrainer::skip(int count) { /*Pula quantidade de nós passado por argumento */
	int openBraceCount = 0;
	SExpressionState state = NONE;
	while (true) {
		char c = getChar();

		if (c == '\0')
			return false;

		if (c == '(') {
			switch (state) {
			case NONE:
				state = SUBLIST;
				++openBraceCount;
				break;
			case SYMBOL:
				--count;
				if (count == 0) {
					pushChar();
					return true;
				}
				state = SUBLIST;
				++openBraceCount;
				break;
			case SUBLIST:
				++openBraceCount;
				break;
			}
		} else if (c == ')') {
			switch (state) {
			case NONE:
				pushChar();
				return false;
			case SYMBOL:
				--count;
				if (count == 0) {
					pushChar();
					return true;
				}
				pushChar();
				return false;
			case SUBLIST:
				--openBraceCount;
				if (openBraceCount == 0) {
					--count;
					if (count == 0)
						return true;
					state = NONE;
				}
				break;
			}
		} else if (isblank(c)) {
			switch (state) {
			case NONE:
				break;
			case SYMBOL:
				--count;
				if (count == 0)
					return true;
				state =NONE;
				break;
			case SUBLIST:
				break;
			}
		} else {
			switch (state) {
			case NONE:
				state = SYMBOL;
				break;
			case SYMBOL:
				break;
			case SUBLIST:
				break;
			}
		}
	}
}

bool
ParserTrainer::in(int levelCount) {//ler a string ao econtrar "(" chama o metodo getChar que avança mais um caracter na string
	while (levelCount > 0) {
		char c = getChar();
		if (c == '\0')
			return false;

		if (c == '(')
			--levelCount;
	}

	return true;
}

bool
ParserTrainer::out(int levelCount) {//Ler a string ao encontrar "(" avança ao encontrar ")" aumenta o contador e avança mais
	while (levelCount > 0) {
		char c = getChar();

		if (c == '\0')
			return false;

		if (c == ')')
			--levelCount;
		else if (c == '(')
			++levelCount;
	}

	return true;
}

std::string
ParserTrainer::take() {//retorna o token da folha
	int openBraceCount = 0;
	skipWhiteSpaces();

	std::string builder;

      	while (true) {
		char c = getChar();

 		if (c == '\0')
			return builder;

		if (c == ')') {
			if (openBraceCount == 0) {
				pushChar();
				return builder;
			}

			--openBraceCount;

			if (openBraceCount == 0) {
				builder+=c;
				return builder;
			}
		} else if (c == '(') {
			++openBraceCount;
		} else if (isblank(c)) {
			if (openBraceCount == 0)
				return builder;
		}

 		builder+=c;
	}
}


std::string
ParserTrainer::EXpress(){//funcao para devolver expressao por no e seus filhos
	std::string builder;
	//std::string no;
	//int cont;

	int openBraceCount = 0;

	for(int i = 0; i<expression.length(); i++){

		char c = getChar();

		if(c=='('){
            builder+='(';
           openBraceCount++;

		 }else if(c==')'){


			 builder+=')';
			 openBraceCount--;

			 /*if(no=="nd")//dando entre para separar o nd
				 builder+="\n";*/

			 if(openBraceCount!=0)
				 builder+=' ';
		} else if (isblank(c)) {


			  if(openBraceCount!=0)
	    		    builder+=' ';

		 }else {

			  builder+=c;
/*
			  no += c;
			  cont++;

			  if(no=="nd" && cont ==2){//imprimir como uma arvores nao esta sendo utilizado no momento

				 // builder+="\n ";
				  cont=0;
				  no="";
			  }else{

				  if(cont==2){
					  cont=0;
					  no="";
				  }
			  }
*/


		 }

         if(openBraceCount==0 && (!isblank(c))){
        	if(index==expression.length()){

        	  // std::cout<<"\n"<<index;
        	}
                return builder;
         }

	}

}


Matriz4d ParserTrainer:: express4d(int num){//futuramente pensar como resolver
/*
	      Matriz4d* transform=NULL;
	      in(num);//abrindo no para pegar posicoes braço superiorL
	       if(take()=="SLT")
			   {
					transform = readTransformationMatrix(SsubExpress);
					if (transform != NULL)
					{
						agente3d.setLupperarm(*(transform));
						std::cout<< "\nBraço SuperiorL: "; agente3d.tostringPartAgent(agente3d.getLmupperarmAgentePosition());

					  }
		}*/

}

int ParserTrainer::getExprLength(){//devolver tamanho da mensagem menos o valor do index atual

	return expression.length()-index;
}


void
ParserTrainer::skipToEnd() {
	index = expression.length();
}
